local pvt_lat = 0
local pvt_lon = 0
local pvt_time = "221230183100"

local nmea_buf = nil
local nmea_decoder = {}

function nmea_split(str, reps)
    local r = {}
    if str == nil then return nil end
    string.gsub(str, "[^" .. reps .. "]+", function(w) table.insert(r, w) end)
    return r
end

function decode_nmeagga(indata)
    --  indata=zbuff.create(100, 0)
    --  indata:pack("A", "$GNGGA,104157.158,2233.1812,N,11353.1275,E,1,19,0.92,92.9,M,-2.9,M,,*51\n")
    local len = indata:used() - 1
    local j = 0
    local n = 1
    local ss = {}

    for i = 0, len do
        v = indata[i]
        if v == string.byte(",") then
            ss[n] = indata:query(j, i - j)
            -- print(i, j, ss[n])
            n = n + 1
            j = i + 1
        end
    end
    print("----")
    print(ss[2])
    print(ss[3])
    print(ss[5])
    print(ss[10])
    print("")

    local latd = 0
    local latm = 0
    local lond = 0
    local lonm = 0
    -- 按照经纬度有六位有效数字计算
    if ss[3] ~= nil then
        latd = tonumber(string.sub(ss[3], 1, 2)) * 1000000
        latm = tonumber(string.sub(ss[3], 3, 4) ..
                            string.sub(ss[3], 6, string.len(ss[3]))) // 60
    end

    if ss[5] ~= nil then
        lond = tonumber(string.sub(ss[5], 1, 3)) * 1000000
        lonm = tonumber(string.sub(ss[5], 4, 5) ..
                            string.sub(ss[5], 7, string.len(ss[5]))) // 60
    end

    pvt_lat = latd + latm
    pvt_lon = lond + lonm

    --  print(pvt_lat, pvt_lon)

    --  local s = indata:query(0, indata:used())

    --  print("decode_nmeagga", s)
    -- a=nmea_split(s, ",")
    --  for k,v in pairs(ss) do
    --    print(k .. "  " .. v)
    -- end
end

function decode_nmearmc(indata)
    local len = indata:used() - 1
    local j = 0
    local n = 1
    local ss = {}

    for i = 0, len do
        v = indata[i]
        if v == string.byte(",") then
            ss[n] = indata:query(j, i - j)
            -- print(i, j, ss[n])
            n = n + 1
            j = i + 1
        end
    end
    -- print("----")
    -- print(ss[10]..ss[2])
    pvt_time = string.sub(ss[10], 5, 6) .. string.sub(ss[10], 3, 4) ..
                   string.sub(ss[10], 1, 2) .. string.sub(ss[2], 1, 6)
    --  print(tonumber(ss[3]))
    --  print(tonumber(ss[5]))
    --  print(tonumber(ss[10]))
    print("RMC", pvt_time)
end

function decode_nmeazda(indata) end

function decode_nmeavtg(indata) end

function init_nmea()
    nmea_buf = zbuff.create(150, 0)
    nmea_decoder["GGA"] = decode_nmeagga
    nmea_decoder["RMC"] = decode_nmearmc
    nmea_decoder["ZDA"] = decode_nmeazda
    nmea_decoder["VTG"] = decode_nmeavtg
end

local function print_zbuff(d)
    str = ""
    for i = 0, d:used() - 1 do str = str .. string.format("%02x ", d[i]) end
    print(str)
end

function nmea_crc(indata, start, len)
    local crc = 0
    for i = start, len - 1 do crc = bit.bxor(crc, indata[i]) end

    return crc
end
   
function input_nmea(indata)

    len = indata:used() - 1
    for i = 0, len do
        v = indata[i]
        if nmea_buf:used() == nmea_buf:len() then
            --      print("nmea too long")
            nmea_buf:seek(0)
            goto continue
        end

        if v == string.byte("$") then
            nmea_buf:seek(0)
            nmea_buf:writeU8(v)
        end
        if nmea_buf:used() == 0 then goto continue end

        --	print(i, v, nmea_buf:used())
        if v ~= string.byte("$") then nmea_buf:writeU8(v) end

        if v == string.byte("\r") or v == string.byte("\n") then
            if nmea_buf:used() < 10 then
                --        print("too short")
                nmea_buf:seek(0)
                goto continue
            else
                len = nmea_buf:used()
                crc = nmea_crc(nmea_buf, 1, nmea_buf:used() - 4)
                s = string.format("%02X", crc)

                if (string.byte(s, 1) ~= nmea_buf[len - 3]) or
                    (string.byte(s, 2) ~= nmea_buf[len - 2]) then
                    sentence = nmea_buf:query(3, 3)
                    -- print("nmea crc error: ",sentence)
                    -- print_zbuffprint_zbuff(nmea_buf)
                else
                    sentence = nmea_buf:query(3, 3)
                    -- print("find nmea ", sentence)
                    local decoder = nmea_decoder[sentence]
                    if decoder ~= nil then decoder(nmea_buf) end
                end

                nmea_buf:seek(0)
            end
        end

        ::continue::
    end
end

function nmea_get() return pvt_lat, pvt_lon, pvt_time end

-- init_nmea()

-- d=zbuff.create(1000, 0)
-- d:pack("A", "$GNGGA,104157.158,2233.1812,N,11353.1275,E,1,19,0.92,92.9,M,-2.9,M,,*51\n")
-- print_zbuff(d)
-- input_nmea(d)
